#include <stdlib.h>
#include <string.h>

#include "crypto/destool.h"
#include "crypto/types.h"
#include "crypto/bits.h"
#include "crypto/errors.h"

// 获取置换密钥
bits *desGetCryptoKey(byte *buffer)
{
    bits *buf = initBits(DES_KEY_BIT_LEN);
    for (int i = 0; i < DES_KEY_BIT_LEN; i++)
    {
        setBit(buf, i, getBitFromArray(buffer, DesTransform[i] - 1));
    }
    return buf;
}
// 获取子密钥
void desGetSubCryptoKeys(bits *subCryptoKeys[], bits *cryptoKey, CRYPTO_OPT opt)
{
    bits *lgroup = initBits(DES_SUB_KEY_GROUP_SIZE);
    bits *rgroup = initBits(DES_SUB_KEY_GROUP_SIZE);
    int tmp, index;

    for (int i = 0; i < DES_SUB_KEY_GROUP_SIZE; i++)
    {
        setBit(lgroup, i, getBit(cryptoKey, i));
    }

    for (int i = DES_SUB_KEY_GROUP_SIZE; i < DES_KEY_BIT_LEN; i++)
    {
        setBit(rgroup, i - DES_SUB_KEY_GROUP_SIZE, getBit(cryptoKey, i));
    }
    // printf("Subbits:\n");
    // printBits(lgroup);
    // printBits(rgroup);

    for (int i = 0; i < 16; i++)
    {
        rotateBits(lgroup, -DesRotations[i]);
        rotateBits(rgroup, -DesRotations[i]);

        // printf("\nround: %d\n", i);
        // printBits(lgroup);
        // printBits(rgroup);

        if (opt == ENCODE)
        {
            index = i;
        }
        else
        {
            index = 15 - i;
        }

        for (int j = 0; j < 24; j++)
        {
            tmp = DesPermuted[j] - 1;
            setBit(subCryptoKeys[index], j, getBit(lgroup, tmp));
        }
        for (int j = 24; j < 48; j++)
        {
            tmp = DesPermuted[j] - 1;
            setBit(subCryptoKeys[index], j, getBit(rgroup, tmp - DES_SUB_KEY_GROUP_SIZE));
        }
    }
}

// des的数据初始化
void desInitData(bits *LR[], byte *data)
{
    int tmp = 0;
    for (int i = 0; i < DES_DATA_GROUP_BIT_LEN; i++)
    {
        tmp = DesInitial[i] - 1;
        if (i >= DES_DATA_SUB_GROUP_BIT_SIZE)
        {
            setBit(LR[1], i - DES_DATA_SUB_GROUP_BIT_SIZE, getBitFromArray(data, tmp));
        }
        else
        {
            setBit(LR[0], i, getBitFromArray(data, tmp));
        }
    }
}

// des每一轮
void desRound(bits *LR[], bits *subCryptoKeys, bits *Rint)
{
    int row, col, index;
    byte buffer[4];
    byte Rbuffer[4];
    byte value;
    memcpy(Rbuffer, LR[1]->data, 4);
    for (int i = 0; i < DES_DATA_EXPANSION_BIT_LEN; i++)
    {
        setBit(Rint, i, getBit(LR[1], DesExpansion[i] - 1));
    }
    operateBits(Rint, subCryptoKeys, BIT_XOR);
    for (int i = 0; i < 4; i++)
    {
        index = 2 * i * 6;
        row = (getBit(Rint, index) << 1) + getBit(Rint, index + 5);
        col = (getBit(Rint, index + 1) << 3) + (getBit(Rint, index + 2) << 2) + (getBit(Rint, index + 3) << 1) + getBit(Rint, index + 4);
        value = DesSbox[2 * i][row][col] << 4;
        index = (2 * i + 1) * 6;
        row = (getBit(Rint, index) << 1) + getBit(Rint, index + 5);
        col = (getBit(Rint, index + 1) << 3) + (getBit(Rint, index + 2) << 2) + (getBit(Rint, index + 3) << 1) + getBit(Rint, index + 4);
        value += DesSbox[2 * i + 1][row][col];
        LR[1]->data[i] = value;
    }
    memcpy(buffer, LR[1]->data, 4);
    for (int i = 0; i < DES_DATA_SUB_GROUP_BIT_SIZE; i++)
    {
        setBit(LR[1], i, getBitFromArray(buffer, DesPbox[i] - 1));
    }
    operateBits(LR[1], LR[0], BIT_XOR);
    memcpy(LR[0]->data, Rbuffer, 4);
}

void desFinalTrans(bits *LR[])
{
    int index;
    byte buffer[8];
    memcpy(buffer, LR[1]->data, 4);
    memcpy(buffer + 4, LR[0]->data, 4);
    for (int i = 0; i < DES_DATA_GROUP_BIT_LEN; i++)
    {
        index = DesFinalTrans[i] - 1;
        if (i >= DES_DATA_SUB_GROUP_BIT_SIZE)
        {
            setBit(LR[1], i - DES_DATA_SUB_GROUP_BIT_SIZE, getBitFromArray(buffer, index));
        }
        else
        {
            setBit(LR[0], i, getBitFromArray(buffer, index));
        }
    }
}